/**
 * @file elf-parse.c
 * @author etcflywy@126.com
 * @brief 
 * @version 0.1
 * @date 2025-11-09
 * 
 * @copyright Copyright (c) 2025
 * 
 */
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "elf-parse.h"
#include "mem.h"


Elf32_Ehdr *elf_header_parse(void *file_content)
{
    return (Elf32_Ehdr *)file_content;
}

Elf32_Phdr *elf_program_header_get(const void *file_content)
{
    return (Elf32_Phdr *)file_content;
}

void elf_mem_loader(void *file_content)
{
    const char *pfile = (const char *)file_content;
    Elf32_Ehdr *elfHeader;
    Elf32_Phdr *pProgramHeader;

    elfHeader = elf_header_parse(file_content);
    if (elfHeader->e_type != ET_EXEC && elfHeader->e_type != ET_DYN) {
        printf("type %d unmatch\r\n", elfHeader->e_type);
        return ;
    }

    printf("programHeader tab size %d number:%d file offset:%d\r\n", elfHeader->e_phentsize, \
        elfHeader->e_phnum,  elfHeader->e_phoff);
    pProgramHeader = elf_program_header_get(&pfile[elfHeader->e_phoff]);
    
    char *addr = allocate_elf_memory_32bit(1024*50);
    if (addr == NULL) {
        printf("malloc elf memory fail\r\n");
        return ;
    }

    //! loader PT_LOAD to memory
    for (int i = 0; i < elfHeader->e_phnum; i++) {
        if (pProgramHeader[i].p_type != PT_LOAD) {
            continue;
        }

        uint32_t vaddr = pProgramHeader[i].p_vaddr;
        uint32_t fsize = pProgramHeader[i].p_filesz;
        uint32_t memsz = pProgramHeader[i].p_memsz;
        uint32_t align =  pProgramHeader[i].p_align;
        uint32_t flags = pProgramHeader[i].p_flags;
        const char *pseg_content = &pfile[pProgramHeader[i].p_offset];
        if (fsize != 0 || memsz != 0) {
            printf("align %d fsize:%d memsz:%d vaddr:%x flags:%d\r\n", align, fsize, memsz, vaddr, flags);
            memcpy((void*)vaddr, pseg_content, fsize);
            if (memsz > fsize) {
                memset((void*)(vaddr+fsize), 0, memsz-fsize);
            }
        }
    }

    int val = ((int (*)())(elfHeader->e_entry))();
    printf("ret val:%d\r\n", val);
}
